<?php
/**
 * Created by PhpStorm.
 * User: mac
 * Date: 2019-03-02
 * Time: 20:34
 */

/**
 * Class process
 * 在子进程里使用管道
 * 管道的读写：
 * $data的长度在Linux系统下最大不超过8K，MacOS/FreeBSD下最大不超过2K
 * 在子进程内调用write，父进程可以调用read接收此数据
 * 在父进程内调用write，子进程可以调用read接收此数据
 *
 * swoole_process::wait(); 只能回收一个子进程，如果开启了多个，要遍历进程池，挨个回收。如果要写成一个守护进程方式的，可以使用while做一个循环
 * 具体写法SWOOLE文档有案例。
 */
class process
{
    public $work_num = 0;
    public $work_array = array();

    public function __construct(array $task_data)
    {
        try {
            $this->work_num = count($task_data);
            $this->createProcess($task_data);
            $this->readRes();
            $this->waitProcess();
        } catch (Exception $exception) {
            echo $exception->getMessage();
        }
    }

    private function createProcess(array $task_data)
    {
        for ($i = 0; $i < $this->work_num; $i++) {
            $process = new swoole_process(function (swoole_process $work) use($task_data, $i) {
                //睡眠三秒模拟执行耗时3秒的程序
                $num = $this->getFunc();
                //往主进程管道里写数据
                $work->write($task_data[$i] . $num . PHP_EOL);
            }, true);
            $pid = $process->start();
            $this->work_array[$pid] = $process;
        }
    }

    private function getFunc()
    {
        sleep(3);
        return mt_rand(100, 999);
    }

    private function readRes()
    {
        foreach ($this->work_array as $value) {
            //从主进程的管道里读取数据
            echo $value->read();
        }
    }

    private function waitProcess()
    {
        for ($i = 0; $i < $this->work_num; $i++) {
            $ret = swoole_process::wait();
            echo $ret['pid'] . 'exit' . PHP_EOL;
        }
    }
}

$task_data = array('zhangsan', 'lisi', 'wangwu', 'zhaoliu', 'houqi');
$res = new process($task_data);